package com.imooc.business.util.report;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @Author Tim
 * @Description:
 * @Version 1.0
 */
public class LunarCalendarUtil {
    private static final int[] LUNAR_INFO = new int[]{19416, 19168, 42352, 21717, 53856, 55632, 91476, 22176, 39632, 21970, 19168, 42422, 42192, 53840, 119381, 46400, 54944, 44450, 38320, 84343, 18800, 42160, 46261, 27216, 27968, 109396, 11104, 38256, 21234, 18800, 25958, 54432, 59984, 28309, 23248, 11104, 100067, 37600, 116951, 51536, 54432, 120998, 46416, 22176, 107956, 9680, 37584, 53938, 43344, 46423, 27808, 46416, 86869, 19872, 42448, 83315, 21200, 43432, 59728, 27296, 44710, 43856, 19296, 43748, 42352, 21088, 62051, 55632, 23383, 22176, 38608, 19925, 19152, 42192, 54484, 53840, 54616, 46400, 46496, 103846, 38320, 18864, 43380, 42160, 45690, 27216, 27968, 44870, 43872, 38256, 19189, 18800, 25776, 29859, 59984, 27480, 21952, 43872, 38613, 37600, 51552, 55636, 54432, 55888, 30034, 22176, 43959, 9680, 37584, 51893, 43344, 46240, 47780, 44368, 21977, 19360, 42416, 86390, 21168, 43312, 31060, 27296, 44368, 23378, 19296, 42726, 42208, 53856, 60005, 54576, 23200, 30371, 38608, 19415, 19152, 42192, 118966, 53840, 54560, 56645, 46496, 22224, 21938, 18864, 42359, 42160, 43600, 111189, 27936, 44448};
    private static final int MIN_YEAR = 1900;
    private static final int MAX_YEAR = 2049;
    private static boolean isLeapYear;
    private static final String START_DATE = "1900-01-30";

    public LunarCalendarUtil() {
    }

    private static int getLeapMonth(int year) {
        return LUNAR_INFO[year - 1900] & 15;
    }

    private static int getLeapMonthDays(int year) {
        if (getLeapMonth(year) != 0) {
            return (LUNAR_INFO[year - 1900] & 983040) == 0 ? 29 : 30;
        } else {
            return 0;
        }
    }

    private static int getMonthDays(int lunarYeay, int month) throws RuntimeException {
        if (month <= 31 && month >= 0) {
            int bit = 1 << 16 - month;
            return (LUNAR_INFO[lunarYeay - 1900] & '\uffff' & bit) == 0 ? 29 : 30;
        } else {
            throw new RuntimeException("月份有错！");
        }
    }

    private static int getYearDays(int year) {
        int sum = 348;

        for(int i = 32768; i >= 8; i >>= 1) {
            if ((LUNAR_INFO[year - 1900] & '\ufff0' & i) != 0) {
                ++sum;
            }
        }

        return sum + getLeapMonthDays(year);
    }

    private static int daysBetween(Date startDate, Date endDate) {
        int days = 0;
        Calendar can1 = Calendar.getInstance();
        can1.setTime(startDate);
        Calendar can2 = Calendar.getInstance();
        can2.setTime(endDate);
        int year1 = can1.get(1);
        int year2 = can2.get(1);
        Calendar can = null;
        if (can1.before(can2)) {
            days -= can1.get(6);
            days += can2.get(6);
            can = can1;
        } else {
            days -= can2.get(6);
            days += can1.get(6);
            can = can2;
        }

        for(int i = 0; i < Math.abs(year2 - year1); ++i) {
            days += can.getActualMaximum(6);
            can.add(1, 1);
        }

        return days;
    }

    private static void checkLunarDate(int lunarYear, int lunarMonth, int lunarDay, boolean leapMonthFlag) throws RuntimeException {
        if (lunarYear >= 1900 && lunarYear <= 2049) {
            if (lunarMonth >= 1 && lunarMonth <= 12) {
                if (lunarDay >= 1 && lunarDay <= 30) {
                    int leap = getLeapMonth(lunarYear);
                    if (leapMonthFlag && lunarMonth != leap) {
                        throw new RuntimeException("非法闰月！");
                    }
                } else {
                    throw new RuntimeException("非法农历天数！");
                }
            } else {
                throw new RuntimeException("非法农历月份！");
            }
        } else {
            throw new RuntimeException("非法农历年份！");
        }
    }

    public static String lunarToSolar(Date date) {
        if (date == null) {
            throw new RuntimeException("日期不能为空");
        } else {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            int lunarYear = cal.get(1);
            int lunarMonth = cal.get(2) + 1;
            int lunarDay = cal.get(5);
            int leapMonth = getLeapMonth(lunarYear);
            boolean leapMonthFlag = leapMonth != 0 && leapMonth == lunarMonth;
            checkLunarDate(lunarYear, lunarMonth, lunarDay, leapMonthFlag);
            int offset = 0;

            int temp;
            int tempMonthDaysCount;
            for(temp = 1900; temp < lunarYear; ++temp) {
                tempMonthDaysCount = getYearDays(temp);
                offset += tempMonthDaysCount;
            }

            if (leapMonthFlag && leapMonth != lunarMonth) {
                throw new RuntimeException("您输入的闰月标志有误！");
            } else {
                if (leapMonth == 0 || lunarMonth < leapMonth || lunarMonth == leapMonth && !leapMonthFlag) {
                    for(temp = 1; temp < lunarMonth; ++temp) {
                        tempMonthDaysCount = getMonthDays(lunarYear, temp);
                        offset += tempMonthDaysCount;
                    }

                    if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
                        throw new RuntimeException("不合法的农历日期！");
                    }

                    offset += lunarDay;
                } else {
                    for(temp = 1; temp < lunarMonth; ++temp) {
                        tempMonthDaysCount = getMonthDays(lunarYear, temp);
                        offset += tempMonthDaysCount;
                    }

                    if (lunarMonth > leapMonth) {
                        temp = getLeapMonthDays(lunarYear);
                        offset += temp;
                        if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
                            throw new RuntimeException("不合法的农历日期！");
                        }

                        offset += lunarDay;
                    } else {
                        temp = getMonthDays(lunarYear, lunarMonth);
                        offset += temp;
                        if (lunarDay > getLeapMonthDays(lunarYear)) {
                            throw new RuntimeException("不合法的农历日期！");
                        }

                        offset += lunarDay;
                    }
                }

                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
                Date myDate = null;

                try {
                    myDate = formatter.parse("1900-01-30");
                    Calendar c = Calendar.getInstance();
                    c.setTime(myDate);
                    c.add(5, offset);
                    myDate = c.getTime();
                    return formatter.format(myDate);
                } catch (Exception var11) {
                    var11.printStackTrace();
                    return null;
                }
            }
        }
    }

    public static String solarToLunar(String solarDate) throws RuntimeException {
        int temp = 0;
        boolean leapMonthFlag = false;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Date myDate = null;
        Date startDate = null;

        try {
            myDate = formatter.parse(solarDate);
            startDate = formatter.parse("1900-01-30");
        } catch (ParseException var12) {
            var12.printStackTrace();
        }

        int offset = daysBetween(startDate, myDate);

        int i;
        for(i = 1900; i <= 2049; ++i) {
            temp = getYearDays(i);
            if (offset - temp < 1) {
                break;
            }

            offset -= temp;
        }

        int lunarYear = i;
        int leapMonth = getLeapMonth(i);
        if (leapMonth > 0) {
            isLeapYear = true;
        } else {
            isLeapYear = false;
        }

        for(i = 1; i <= 12; ++i) {
            if (i == leapMonth + 1 && isLeapYear) {
                temp = getLeapMonthDays(lunarYear);
                isLeapYear = false;
                leapMonthFlag = true;
                --i;
            } else {
                temp = getMonthDays(lunarYear, i);
            }

            offset -= temp;
            if (offset <= 0) {
                break;
            }
        }

        offset += temp;
        return "阴历：" + lunarYear + "年" + (leapMonthFlag && i == leapMonth ? "闰" : "") + i + "月" + offset + "日";
    }
}

